﻿using System;
using System.Configuration;
using System.Web.Configuration;
using AT.IBMS.Framework.Configuration;

namespace AT.IBMS.Framework.Logging
{
    public class Logger
    {

        private LogElement section;

        internal Logger()
        {
            section = FrameworkManager.FrameworkConfigurationSettings.Log;
        }

        private WriteLogProviderBase CreateLogProvider(string providerName)
        {

            ProviderSettings providerSettings;

            providerSettings = section.Providers[providerName];
            return (WriteLogProviderBase)ProvidersHelper.
                InstantiateProvider(providerSettings,
                typeof(WriteLogProviderBase));

        }

        /// <summary>
        /// 写入日志。
        /// </summary>
        /// <param name="log">要写入的日志实体。</param>
        public void Write(LogEntry log)
        {

            string[] providersName;
            WriteLogProviderBase provider;

            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            if (log.Categories.Count == 0)
            {
                log.AppendCategory(section.DefaultCategory);
            }

            providersName = section.ProviderName.Split(',');

            foreach (var item in providersName)
            {
                provider = CreateLogProvider(item);
                provider.Write(log);
            }

        }

        /// <summary>
        /// 写入日志。
        /// </summary>
        /// <param name="message">日志信息。</param>
        public void Write(string message)
        {
            Write(CreateLogEntry(message));
        }

        private LogEntry CreateLogEntry(string message)
        {

            LogEntry log;

            log = new LogEntry();
            log.Message = message.ToString();
            log.AppendCategory(section.DefaultCategory);
            return log;

        }

        /// <summary>
        /// 在Sql Server数据库中创建用于支持日志组件的表（TLog）和存储过程（WriteLog）。
        /// 注意：如果数据库中已存在，那么先删除。然后重新创建。
        /// </summary>
        public void CreateTableAndProcedureToDatebase()
        {

            string[] providersName;
            WriteLogToDatabaseProvider databaseProvider;

            providersName = section.ProviderName.Split(',');

            foreach (var item in providersName)
            {

                databaseProvider = CreateLogProvider(item) as WriteLogToDatabaseProvider;

                if (databaseProvider != null)
                {
                    CreateTableAndProcedureToDatebase(databaseProvider.ConnectionStringName);
                }

            }

        }

        private void CreateTableAndProcedureToDatebase(string connectionStringName)
        {

            //删除表。
            FrameworkManager.CreateDataProvider(connectionStringName).ExecuteNonQuery("IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TLog]') AND type in (N'U')) DROP TABLE [dbo].[TLog]");

            //删除存储过程。
            FrameworkManager.CreateDataProvider(connectionStringName).ExecuteNonQuery("IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[WriteLog]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[WriteLog]");

            //创建表。
            FrameworkManager.CreateDataProvider(connectionStringName).ExecuteNonQuery("CREATE TABLE [dbo].[TLog]([id] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,[message] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NULL,[title] [nvarchar](500) COLLATE Chinese_PRC_CI_AS NULL,[categories] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NULL,[priority] [int] NULL,[eventId] [int] NULL,[severity] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,[machineName] [nvarchar](500) COLLATE Chinese_PRC_CI_AS NULL,[timeStamp] [datetime] NULL,[extendedProperties] [nvarchar](max) COLLATE Chinese_PRC_CI_AS NULL,[appDomainName] [nvarchar](500) COLLATE Chinese_PRC_CI_AS NULL,[processId] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,[processName] [nvarchar](500) COLLATE Chinese_PRC_CI_AS NULL,[managedThreadName] [nvarchar](500) COLLATE Chinese_PRC_CI_AS NULL,CONSTRAINT [PK_TLog] PRIMARY KEY CLUSTERED ([id] ASC)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]) ON [PRIMARY]");

            //创建存错过程。
            FrameworkManager.CreateDataProvider(connectionStringName).ExecuteNonQuery("CREATE PROCEDURE [dbo].[WriteLog] @id NVARCHAR(50) ,@message NVARCHAR(MAX) ,@title NVARCHAR(500) ,@categories NVARCHAR(MAX) ,@priority INT ,@eventId INT ,@severity NVARCHAR(50) ,@machineName NVARCHAR(500) ,@timeStamp DATETIME ,@extendedProperties NVARCHAR(MAX) ,@appDomainName NVARCHAR(500) ,@processId NVARCHAR(50) ,@processName NVARCHAR(500) ,@managedThreadName NVARCHAR(500) AS BEGIN INSERT  INTO dbo.TLog( id ,message ,title ,categories ,priority ,eventId ,severity ,machineName ,timeStamp ,extendedProperties ,appDomainName ,processId ,processName ,managedThreadName) VALUES  ( @id , @message , @title , @categories , @priority , @eventId , @severity ,@machineName ,@timeStamp ,@extendedProperties ,@appDomainName ,@processId , @processName ,@managedThreadName ) END");

        }

    }
}
